package com.winit.openapi.filter;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.winit.openapi.apiadapter.controller.util.ApiAdapteUtil;
import com.winit.openapi.apiadapter.controller.util.ApiClient;
import com.winit.openapi.constants.ApiConstant;
import com.winit.openapi.constants.ErrorCode;
import com.winit.openapi.exception.ApiException;
import com.winit.openapi.model.ResponseMsgFor3E;
import com.winit.openapi.util.APISysConfigUtil;
import com.winit.openapi.util.Config;
import com.winit.openapi.util.ValidateUtil;

/**
 * api过滤器,过滤AD接口/ADInterface/api,/services/ModelADService,/services/
 * ExternalSales 如果OpenAPI相应接口做了适配，则转发至OpenAPI，否则转发至AD执行
 * 
 * @version <pre>
 * Author	Version		Date		Changes
 * minghao.deng 	1.0  		2016年11月22日 	Created
 *
 * </pre>
 * @since 1.
 */
public class ApiServletFilter implements Filter {

    private static final Logger logger              = LoggerFactory.getLogger(ApiServletFilter.class);

    /**
     * 3E接口URL前缀
     */
    private static final String AD_THIRD_API_SUFFIX = "/api";

    private Config              config;
    
    private APISysConfigUtil                       apiSysConfigUtil;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

        WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(filterConfig.getServletContext());
        config = (Config) ctx.getBean("config");
        apiSysConfigUtil = (APISysConfigUtil) ctx.getBean("apiSysConfigUtil");
        logger.info("servlet初始化完成...");
    }

    @Override
    public void doFilter(ServletRequest arg1, ServletResponse arg2, FilterChain chain) throws IOException,
                                                                                      ServletException {
        HttpServletRequest request = (HttpServletRequest) arg1;
        HttpServletResponse response = (HttpServletResponse) arg2;
        String uri = request.getRequestURI();
        String contentType = request.getContentType();
       // String originalUrl = request.getRequestURL().toString();
        String method = request.getMethod();
        ApiClient client = new ApiClient();
        String result = null;
       //标识接口是否已經做适配
        boolean isAdapted = false;
        // 3e接口json格式
        if (uri.contains(AD_THIRD_API_SUFFIX) && ApiConstant.METHOD_POST.equalsIgnoreCase(method)) {
            String action = getAction(request, response);
            // 未做API适配的接口转发至ERP执行老接口
            if (ApiAdapteUtil.getAdapted_api_list().contains(action)) {
                isAdapted = true;
                if ("createOutboundOrder".equals(action) || "createOutboundInfo".equals(action)
                    || "createOutboundOrderFx".equals(action)) {

                    isAdapted = apiSysConfigUtil.isOutboundOrderSupport();

                } else if ("registerProduct".equals(action)) {
                    isAdapted = apiSysConfigUtil.isRegisterProductAdapted();
                } else if ("queryWarehouse".equals(action)) {
                    isAdapted = apiSysConfigUtil.isQueryWarehouseAdapted();
                } else if ("queryProductInventoryList4Page".equals(action)
                           || "queryProductInventoryDetail".equals(action) || "queryWarehouseStorage".equals(action)) {
                    isAdapted = apiSysConfigUtil.isWarehouseInventoryAdapted();
                }
                if (isAdapted) {
                    chain.doFilter(request, response);
                    return;
                }
            }
        }
        String rewriteURLFlag = apiSysConfigUtil.getConfigValueByKey("API_REWRITE_AD_URL_FLAG");
        String targetUrl = null;
        if (StringUtils.isNotBlank(rewriteURLFlag) && "true".equalsIgnoreCase(rewriteURLFlag)) {
            targetUrl = config.getErpDomain() + getOriginalContextPath(uri);
        } else {
            targetUrl = config.getErpDomain() + uri;
        }
        result = client.sendRequest(request, targetUrl);
        doReturn(response, result, contentType);
//       logger.info("API原始URL：" + originalUrl + " 请求方式：" + method + " 转发至" + targetUrl);
//       logger.info("适配结果：\r" + result);

    }
    
    private  String getOriginalContextPath(String uri) {
        if (StringUtils.isBlank(uri)) {
            return StringUtils.EMPTY;
        }
        if (APISysConfigUtil.isDebug()) {
            logger.info("开始URLRewrite:" + uri);
        }
        String adContextPath = "ADInterface";
        String openapiContextPath = "openapi";
        if (uri.contains(openapiContextPath)) {
            String result = uri.replace(openapiContextPath, adContextPath);
            if (APISysConfigUtil.isDebug()) {
                logger.info("URLRewrite结果：" + result);
            }
            return result;
        }
        
        return uri;

    }
    

    /**
     * 返回json消息
     * 
     * @param response
     * @param requestMsg
     * @param responseMsg
     * @throws IOException
     */
    private void doReturn(ServletResponse response, String responseStr, String contextType) throws IOException {
        if (StringUtils.isEmpty(responseStr)) {
            return;
        }

        PrintWriter out = null;
        try {
            response.setContentType(contextType);
            response.setCharacterEncoding(ApiConstant.CHARSET_UTF8);
            out = response.getWriter();
            out.write(responseStr);
            out.flush();

        } finally {
            if (out != null) {
                out.close();
            }
        }
    }

    private String getAction(ServletRequest request, HttpServletResponse response) throws IOException {
        JSONObject json = null;
        String inputJsonStr = null;
        String encoding = request.getCharacterEncoding();

        try {
            if (StringUtils.isBlank(encoding)) {
                encoding = ApiConstant.CHARSET_UTF8;
            }
            inputJsonStr = getRrequestData(request,response);

//            if (StringUtils.isBlank(inputJsonStr)) {
//                throw new ApiException(ErrorCode.ILLEGAL_JSON_STRING);
//            }
            json = JSONObject.parseObject(inputJsonStr);
            request.setAttribute(ApiConstant.SOURCE_INPUT_STRING, inputJsonStr);

        } catch (JSONException e) {
            ResponseMsgFor3E msg = new ResponseMsgFor3E();
            // 3E非法json错误码
            msg.setCode(400006);
            msg.setMsg("Illegal json string,please check.");
            logger.warn("illegal json string: " + inputJsonStr);
            doReturn(response, JSON.toJSONString(msg), request.getContentType());
            throw new ApiException(ErrorCode.ILLEGAL_JSON_STRING);
        }
        ValidateUtil.validNotNull(json, "action");
        return json.getString("action");
    }

    private String getRrequestData(ServletRequest request,HttpServletResponse response) throws IOException {
        String encoding = request.getCharacterEncoding();
        String inputJsonStr = null;
        if (StringUtils.isBlank(encoding)) {
            encoding = ApiConstant.CHARSET_UTF8;
        }
        try {
            inputJsonStr = IOUtils.toString(request.getInputStream(), encoding);
        } catch (IOException e) {
            ResponseMsgFor3E msg = new ResponseMsgFor3E();
            //3E非法json错误码
            msg.setCode(100007);
            msg.setMsg("非法的JSON字符串,请仔细核对JOSN格式是否正确.");
            logger.warn("非法的JSON字符串: " + inputJsonStr);
            doReturn(response, JSON.toJSONString(msg), request.getContentType());
            throw new ApiException(ErrorCode.CHARSET_NOT_SUPORT);
        }
        return inputJsonStr;
    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }


}
